package biolabs.gui;

import java.awt.Component;
import java.util.LinkedList;
import java.util.List;

import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import biolabs.core.Experiment;
import biolabs.core.ExperimentListener;
import biolabs.core.ApplicationListener;

/**
 * UI component that displays a list of all active experiments.
 *
 * @author Tomas Mikula
 */
class ExperimentList implements UIComponent, ApplicationListener {

	private class ExperimentListenerImpl implements ExperimentListener {

		@Override
		public void experimentClosed(Experiment exp) {
			int i = experiments.indexOf(exp);
			if(i != -1) {
				experiments.remove(i);
				for(ListDataListener l: dataListeners)
					l.intervalRemoved(new ListDataEvent(exp.getName(), ListDataEvent.INTERVAL_REMOVED, i, i));
			}
		}

		@Override
		public void experimentStarted(Experiment exp) {
			// do nothing
		}

		@Override
		public void experimentStopped(Experiment exp) {
			// do nothing
		}
	}

	private class ListModelImpl implements ListModel {

		@Override
		public void addListDataListener(ListDataListener l) {
			dataListeners.add(l);
		}

		@Override
		public void removeListDataListener(ListDataListener l) {
			dataListeners.remove(l);
		}

		@Override
		public String getElementAt(int index) {
			return experiments.get(index).getName();
		}

		@Override
		public int getSize() {
			return experiments.size();
		}
	}

	private final JComponent content;
	private final JList expList;

	private final List<Experiment> experiments = new LinkedList<Experiment>();
	private final List<ListDataListener> dataListeners = new LinkedList<ListDataListener>();
	private final List<ExperimentSelectionListener> selectionListeners = new LinkedList<ExperimentSelectionListener>();
	private final ExperimentListener closeListener = new ExperimentListenerImpl();

	public ExperimentList() {

		JLabel label = new JLabel("Active experiments");
		expList = new JList(new ListModelImpl());
		expList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		expList.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent evt) {
				Experiment selExp;
				int i = expList.getSelectedIndex();
				if(i == -1)
					selExp = null;
				else
					selExp = experiments.get(i);

				for(ExperimentSelectionListener l: selectionListeners)
					l.experimentSelected(selExp);
			}
		});

		label.setAlignmentX(0.5f);
		expList.setMaximumSize(Stage.UNLIMITED_SIZE);

		content = Box.createVerticalBox();
		content.add(label);
		content.add(expList);
	}

	@Override
	public Component getContent() {
		return content;
	}

	@Override
	public void experimentCreated(Experiment exp) {
		int i = experiments.size();
		experiments.add(exp);
		for(ListDataListener l: dataListeners)
			l.intervalAdded(new ListDataEvent(exp.getName(), ListDataEvent.INTERVAL_ADDED, i, i));
		exp.addListener(closeListener);
	}

	public void addSelectionListener(ExperimentSelectionListener l) {
		selectionListeners.add(l);
	}

	public void removeSelectionListener(ExperimentSelectionListener l) {
		selectionListeners.remove(l);
	}
}
